#ifndef DOD_H
#define DOD_H

//include dependance file
#include "apr.h"
#include "apr_time.h"
#include "apr_shm.h"
#include "apr_pools.h"
#include "apr_proc_mutex.h"
#include "httpd.h"
#include "http_log.h"

#define DOD_STAT_HOST_MAX_NUM 100 /*max host num to intend to stat or checking*/
#define DOD_FORBIDDEN_HOST_MAX_NUM 1000 /*max forbidden-ip records count*/
#define DOD_DEFAULT_REQUEST_COUNT_LIMIT 60
#define DOD_DEFAULT_STAT_RANGE_TIME 1 //minutes
#define DOD_GLOBAL_INFO_SHM_FILE NULL  //shm file
#define DOD_FORBIDDEN_LOG_FILE "logs/dod_forbidden_log" //forbidden log
#define DOD_GLOBAL_INFO_SIZE sizeof(dod_global_info_t)

/*dod status after checked*/
#define DOD_CHECKED_FORBIDDEN 0
#define DOD_CHECKED_ALLOWED 1

/*for mutex*/
#define DOD_MUTEX_LOCK_TYPE APR_LOCK_DEFAULT
#define DOD_GLOBAL_INFO_MUTEX_FILE NULL

#define DOD_DEBUG_ON 0

#if DOD_DEBUG_ON

#define DOD_DEBUG(dod_debug_str) ap_log_error(APLOG_MARK, APLOG_ERR, APR_INCHILD, NULL, dod_debug_str);

#else

#define DOD_DEBUG(dod_debug_str)

#endif

/*stat ip each info type*/
typedef struct dod_stat_ip_info_t dod_stat_ip_info_t;

/*forbidden ip each info type*/
typedef struct dod_forbidden_ip_info_t dod_forbidden_ip_info_t;

/*global stat info type*/
typedef struct dod_global_stat_info_t dod_global_stat_info_t;

/*global forbidden into type*/
typedef struct dod_global_forbidden_info_t dod_global_forbidden_info_t;

/*global block info*/
typedef struct dod_global_info_t dod_global_info_t;

typedef apr_uint32_t apr_uintip_t;

struct dod_stat_ip_info_t{ /*for checking if ip valid?*/
    apr_uintip_t ip_addr;
    apr_uint16_t request_count;
    apr_time_t first_request_time;
};

struct dod_global_stat_info_t{ /*global stat info*/
    dod_stat_ip_info_t ips[DOD_STAT_HOST_MAX_NUM]; //record all stat ips info.
};

struct dod_forbidden_ip_info_t{ /*record forbidden ip info*/
    apr_uintip_t ip_addr; 
    apr_uint16_t forbidden_count;
    apr_time_t last_forbidden_time; //the last time time.
};

struct dod_global_forbidden_info_t{ /*record all forbidden ips info*/
     dod_forbidden_ip_info_t ips[DOD_FORBIDDEN_HOST_MAX_NUM];
};

struct dod_global_info_t{
    dod_global_stat_info_t stat_rec; //for stat or checking ips info.
    dod_global_forbidden_info_t forbidden_rec; // record forbidden ips info;
};


#ifdef __cplusplus/*cplusplus*/
extern "C" {
#endif


/*
 *@brief create the shared memory invoked in the parent process.
 */
APR_DECLARE(apr_status_t) dod_shm_create(apr_pool_t * pool);

/*
 *@brief create the mutex invoked in the parent process
 */
APR_DECLARE(apr_status_t) dod_mutex_create(apr_pool_t * pool);

/*
 *@brief Create the dod global info with the shared memory.
 */
APR_DECLARE(static dod_global_info_t *) dod_global_info_open();

/*
 *@brief Check if the client ip is forbidden.
 *@param ip Client ip address.
 *       port Client ip port.
 */ 
APR_DECLARE(apr_uint16_t) dod_check(char * ip);

/*
 *@brief update forbidden(black list)  ips info.
 *@param forbidden_ips_ptr forbidden ips list ptr
 *@param ip_addr ip address(int)
 *@param current_time 
 */
APR_DECLARE(void) dod_global_forbidden_info_update(dod_global_forbidden_info_t * forbidden_rec_ptr, apr_uintip_t ip_addr, apr_time_t current_time);


/*
 *@brief Check if ip_addr in the black list;
 */
APR_DECLARE(apr_uint16_t) dod_check_in_forbidden_list(dod_global_forbidden_info_t * forbidden_rec_ptr, apr_uintip_t ip_addr);

/*
 *@brief open dod_forbidden_log_file in the parent process;
 */
APR_DECLARE(apr_status_t) dod_forbidden_log_open(apr_pool_t * pool);

/*
 *@brief log info to dod forbidden log file after being fobidded.
 */
APR_DECLARE(static apr_status_t) dod_forbidden_log(apr_uintip_t forbidden_ip_addr, apr_time_t forbidden_time);

#ifdef __cplusplus /*end cplusplus*/
}
#endif

#endif  /*end DOD_H*/
